#include <stdio.h>
#include "kfifo.h"
#include "main.h"	
#include "app_user.h"
#include "msg.h"
#include "hall.h"
#include "earbud_cmd.h"
#include "sy8801.h"
#include "led.h"
#include "sw_timer.h"
#include "key.h"
#include "tim.h"
#include "earbud_wq_comm.h"
#include "ntc.h"


extern void SystemClock_Config(void);


APP_INFO app_info = {0};

uint8_t charge_reset_flag = 0;
uint8_t app_l_charge_reset_timer = 0xff;
uint8_t app_r_charge_reset_timer = 0xff;

uint8_t app_sleep_timer = 0xff;
uint8_t app_bat_server_timer = 0xff;
uint8_t app_bat_disp_timer = 0xff;


void app_charge_reset_delay_callback(void)
{
    BOX_LOG("charge_reset_delay_callback: 0x%x\n", charge_reset_flag);
    
    if(charge_reset_flag & (1<<EAR_L))
    {
        charge_reset_flag &= ~(1<<EAR_L);
        app_l_charge_reset_timer = 0xff;
    }
    else if(charge_reset_flag & (1<<EAR_R))
    {
        charge_reset_flag &= ~(1<<EAR_R);
        app_r_charge_reset_timer = 0xff;
    }
}

void app_charge_reset_timer_start(uint8_t role)
{
    if(role == EAR_L)
    {
        if(app_l_charge_reset_timer != 0xff)
            sw_timer_stop(app_l_charge_reset_timer);
        app_l_charge_reset_timer = sw_timer_start(EAR_CHARGE_RESET_TIME, 0, app_charge_reset_delay_callback);
    }
    else
    {
        if(app_r_charge_reset_timer != 0xff)
            sw_timer_stop(app_r_charge_reset_timer);
        app_r_charge_reset_timer = sw_timer_start(EAR_CHARGE_RESET_TIME, 0, app_charge_reset_delay_callback);
    }
}

void app_charge_reset_timer_stop(uint8_t role)
{
    if(role == EAR_L)
    {
        if(app_l_charge_reset_timer != 0xff)
            app_l_charge_reset_timer = sw_timer_stop(app_l_charge_reset_timer);
    }
    else
    {
        if(app_r_charge_reset_timer != 0xff)
            app_r_charge_reset_timer = sw_timer_stop(app_r_charge_reset_timer);
    }
}

void app_in_box_handle(uint8_t role)
{
    if(role == EAR_L)
    {
        app_info.ear_state[EAR_L] = EAR_IN_BOX;
        BOX_LOG("L in box\n");
    }
    else
    {
        app_info.ear_state[EAR_R] = EAR_IN_BOX;
        BOX_LOG("R in box\n");
    }

    if(app_info.box_state == CLOSE_BOX)
        return;
    
    app_led_set_mode(LED_MODE_BLUE_ON_1S);
    earbud_delay_start_comm(role);
}




void app_out_box_handle(uint8_t role)
{
    if(role == EAR_L)
        BOX_LOG("L out box\n");
    else
        BOX_LOG("R out box\n");

    BOX_LOG("box_state: %d, 0x%x\n", app_info.box_state, charge_reset_flag);

#if (SUPPORT_WQ_COMM)
    if(app_info.box_state == OPEN_BOX)
        return;
#endif

    if(earbud_comm_is_activity(role))
    {
        BOX_LOG("is comm ignore: %d\n", role);
        return;
    }
    
    if((role == EAR_L) && (charge_reset_flag & (1<<EAR_L)))
    {
        BOX_LOG("L charge reset\n");
        return;
    }
    if((role == EAR_R) && (charge_reset_flag & (1<<EAR_R)))
    {
        BOX_LOG("R charge reset\n");
        return;
    }
    
#if 1
    sy8801_ear_5v_output_disable(1<<role);
    
    if(app_info.box_state == OPEN_BOX)
    {
        earbud_stop_comm(role);
        app_info.ear_state[role] = EAR_OUT_BOX;
    }
    else if(app_info.box_state == CLOSE_BOX)
    {
        if(role == EAR_L)
            BOX_LOG("L charge full\n");
        else
            BOX_LOG("R charge full\n");

        app_user_enter_sleep();
    }
#endif
}


void app_open_box_handle(void)
{
    BOX_LOG("open box\n");
    app_info.box_state = OPEN_BOX;

    app_user_sleep_timer_stop();

    charge_reset_flag = 0;
    app_charge_reset_timer_stop(EAR_L);
    app_charge_reset_timer_stop(EAR_R);
    
    if(app_info.ear_state[EAR_L] == EAR_IN_BOX)
    {
        earbud_delay_start_comm(EAR_L);
        earbud_comm_send_cmd(EAR_L, CMD_OPENCASE);
    }

    if(app_info.ear_state[EAR_R] == EAR_IN_BOX)
    {
        earbud_delay_start_comm(EAR_R);
        earbud_comm_send_cmd(EAR_R, CMD_OPENCASE);
    }
}

void app_close_box_callback(uint8_t role)
{
    BOX_LOG("close box callback: %d, %d, %d\n", role, app_info.ear_state[EAR_L], app_info.ear_state[EAR_R]);
    
    if(role == EAR_L)
    {
        earbud_stop_comm(EAR_L);
        BOX_LOG("L out 5V\n");
        charge_reset_flag |= (1<<EAR_L);
        sy8801_ear_5v_output_enable(1<<EAR_L);
        app_charge_reset_timer_start(EAR_L);
    }

    if(role == EAR_R)
    {
        earbud_stop_comm(EAR_R);
        BOX_LOG("R out 5V\n");
        charge_reset_flag |= (1<<EAR_R);
        sy8801_ear_5v_output_enable(1<<EAR_R);
        app_charge_reset_timer_start(EAR_R);
    }
}

void app_close_box_handle(void)
{
    BOX_LOG("close box handle: %d, %d\n", app_info.ear_state[EAR_L], app_info.ear_state[EAR_R]);
    app_info.box_state = CLOSE_BOX;

    if(app_info.ear_state[EAR_L] == EAR_IN_BOX)
    {
        earbud_cmd_clear(EAR_L);
        earbud_comm_delay_timer_stop(EAR_L);
        earbud_comm_send_cmd(EAR_L, CMD_CLOSECASE);
    }

    if(app_info.ear_state[EAR_R] == EAR_IN_BOX)
    {
        earbud_cmd_clear(EAR_R);
        earbud_comm_delay_timer_stop(EAR_R);
        earbud_comm_send_cmd(EAR_R, CMD_CLOSECASE);
    }

    if(app_info.usb_state)
    {
        BOX_LOG("usb in, no sleep\n");
        app_user_sleep_timer_stop();
        return;
    }
    
    if(app_info.ear_state[EAR_L] != EAR_IN_BOX 
        && app_info.ear_state[EAR_R] != EAR_IN_BOX)
    {
        app_user_enter_sleep();
    }
}

void app_usb_in_handle(void)
{
    BOX_LOG("usb in\n");
    app_info.usb_state = 1;
    
    app_led_set_mode(LED_MODE_RED_ON);
}

void app_usb_out_handle(void)
{
    BOX_LOG("usb out %d\n", app_info.bat_state);
    app_info.usb_state = 0;

    if(app_info.bat_state == CHARGE_RUN)
        app_led_set_mode(LED_MODE_RED_OFF);
    else if(app_info.bat_state == CHARGE_FULL)
        app_led_set_mode(LED_MODE_BLUE_OFF);
    app_info.bat_state = CHARGE_IDLE;


    if(app_info.ear_state[EAR_L] != EAR_IN_BOX 
        && app_info.ear_state[EAR_R] != EAR_IN_BOX)
    {
        app_user_enter_sleep();
    }
}

uint8_t app_bat_get_level(void)
{
    return app_info.bat_level;
}

void app_bat_handle(void)
{
    uint16_t bat = app_get_sy8801_battery();
    app_info.bat_level = (bat - 3200) * 100 / (4200-3200);
    
    //BOX_LOG("bat vol: %d, %d\n", bat, app_info.bat_level);
    app_ntc_handle();
}

void app_bat_server_stop(void)
{
    if(app_bat_server_timer != 0xff)
        app_bat_server_timer = sw_timer_stop(app_bat_server_timer);
}

void app_bat_server_start(void)
{
    app_bat_server_stop();
    app_bat_server_timer = sw_timer_start(2000, 1, app_bat_handle);
}

#if (SUPPORT_SY8801_LED)
void app_bat_callback(void)
{
    app_bat_disp_timer = 0xff;
    app_sy880x_set_led(0);
}
#endif

void app_bat_disp(void)
{
#if (SUPPORT_SY8801_LED)
    if(app_info.bat_level > 95)
        app_sy880x_set_led(0x0f);
    else if(app_info.bat_level > 75)
        app_sy880x_set_led(0x07);
    else if(app_info.bat_level > 50)
        app_sy880x_set_led(0x03);
    else if(app_info.bat_level > 25)
        app_sy880x_set_led(0x01);
    else
        app_sy880x_set_led(0x00);

    BOX_LOG("bat disp: %d, %d\n", app_get_sy8801_battery(), app_info.bat_level);
    
    if(app_bat_disp_timer != 0xff)
        sw_timer_stop(app_bat_disp_timer);
    app_bat_disp_timer = sw_timer_start(2000, 0, app_bat_callback);
#endif
}


void app_msg_sys_handle(uint8_t msg_id, uint8_t* data, uint8_t len)
{
	switch(msg_id)
	{
		case MSG_SY880X_IRQ:
#if (SUPPORT_WQ_COMM)
            if(earbud_wq_comm_is_en())
                return;
#endif
			app_sy880x_state_handle();
			break;
		case MSG_HALL_IRQ:
			app_hall_handle();
			break;
		
		case MSG_EAR_IN_BOX:
            app_in_box_handle(data[0]);
			break;
		case MSG_EAR_OUT_BOX:
            app_out_box_handle(data[0]);
			break;
			
		case MSG_OPEN_BOX:
            app_open_box_handle();
			break;
		case MSG_CLOSE_BOX:
            app_close_box_handle();
			break;
		
		case MSG_USB_IN:
            app_usb_in_handle();
			break;
		case MSG_USB_OUT:
            app_usb_out_handle();
			break;

        case MSG_BAT_CHARGE:
            BOX_LOG("bat charge start\n");
            app_info.bat_state = CHARGE_RUN;
            break;
         case MSG_BAT_CHARGE_STOP:
            BOX_LOG("bat charge stop\n");
            //app_info.bat_state = CHARGE_IDLE;
            break;
		case MSG_BAT_CHARGE_FULL:
            BOX_LOG("bat charge full\n");
            app_led_set_mode(LED_MODE_RED_OFF);
            app_led_set_mode(LED_MODE_BLUE_ON);
            app_info.bat_state = CHARGE_FULL;
            break;
            
////////////////////////////////////////	key
		case MSG_KEY_CLICK:
			BOX_LOG("key click\n");
            app_bat_disp();
			break;
		case MSG_KEY_DOUBLE:
			BOX_LOG("key double\n");
			break;
        case MSG_KEY_TRIPLE:
			BOX_LOG("key triple\n");
			break;
		case MSG_KEY_LONG_1S:
			BOX_LOG("key long 1S\n");
			break;
		case MSG_KEY_LONG_3S:
			BOX_LOG("key long 3S\n");
			earbud_enter_pair();
			break;
		case MSG_KEY_LONG_6S:
			BOX_LOG("key long 6S\n");
			earbud_factory_reset();
			break;

        case MSG_NTC_IDLE:
            BOX_LOG("MSG_NTC_IDLE\n");
            break;
        case MSG_NTC_LOW_TEMP:
            BOX_LOG("MSG_NTC_LOW_TEMP\n");
            break;
        case MSG_NTC_HIGH_TEMP:
            BOX_LOG("MSG_NTC_HIGH_TEMP\n");
            break;
        
		default:
			BOX_LOG("msg: %d\n", msg_id);
		break;
	}
}

void app_msg_handle(void)
{
	uint8_t msg_type, msg_id;
	uint8_t buf[32], len;
	
	msg_type = app_msg_get(&msg_id, buf, &len);
	if(msg_type == MSG_TYPE_NULL)
		return;
	
	if(msg_type == MSG_TYPE_SYS)
	{
		app_msg_sys_handle(msg_id, buf, len);
	}
#if (SUPPORT_UART_COMM)
	else if(msg_type == MSG_TYPE_UART)
	{
		earbud_cmd_handle(msg_id, buf, len);
	}
#endif
}

///////////////////////////////////////////////////////////////
//wakeup1   PA0     hall
//wakeup2   PC13    key
//wakeup4   PA2     tx2
//wakeup5   PC5     rx3
void enter_sleep_callback(void)
{
    BOX_LOG("enter sleep\n");
    app_sleep_timer = 0xff;
    
    if(app_info.usb_state)
    {
        BOX_LOG("usb in, no sleep\n");
        return;
    }
    
#if 1
    app_sy880x_enter_sleep();
    HAL_SuspendTick();
    MX_TIM_ALL_Deinit();
    
    __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH);
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN5_LOW);
    HAL_PWR_EnterSTANDBYMode();
    //HAL_PWREx_EnterSHUTDOWNMode();
#else
    app_sy880x_enter_sleep();
    i2c2_deinit();
    uart1_deinit();
    HAL_SuspendTick();
    MX_TIM_ALL_Deinit();
    
    //__HAL_RCC_PWR_CLK_ENABLE();
    //HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH);
    //HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);
    //HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN5_LOW);
    
    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
    SystemClock_Config();
    app_sys_init();
    printf("stop mode2, exit\n");
#endif
}

void app_user_sleep_timer_stop(void)
{
    if(app_sleep_timer != 0xff)
        app_sleep_timer = sw_timer_stop(app_sleep_timer);
}

void app_user_enter_sleep(void)
{
    BOX_LOG("delay enter sleep, 5S\n");
    app_user_sleep_timer_stop();
    app_sleep_timer = sw_timer_start(5000, 0, enter_sleep_callback);
}

void app_user_sleep_wakeup(void)
{
    if(PWR->SR1 & 0x01)
    {
        BOX_LOG("sleep wakeup, hall\n");
        PWR->SCR |= 0x01;   //clear flag
    }
    if(PWR->SR1 & 0x02)
    {
        BOX_LOG("sleep wakeup, key\n");
        PWR->SCR |= 0x02;   //clear flag
    }
    if(PWR->SR1 & 0x10)
    {
        BOX_LOG("sleep wakeup, sy8801\n");
        PWR->SCR |= 0x10;   //clear flag
    }
    
#if 0
    printf("sleep wakeup, unknown\n");
    printf("PWR->CR: 0x%x, 0x%x, 0x%x, 0x%x\n", PWR->CR1, PWR->CR2, PWR->CR3, PWR->CR4);
    printf("PWR->SR: 0x%x, 0x%x\n", PWR->SR1, PWR->SR2);
#endif
}


void app_user_init(void)
{
    app_info.box_state = 0xff;
    app_info.ear_state[EAR_L] = EAR_OUT_BOX;
    app_info.ear_state[EAR_R] = EAR_OUT_BOX;

    app_user_sleep_wakeup();
    app_bat_server_start();
    
#if (SUPPORT_UART_COMM)
    earbud_comm_init();
#if (SUPPORT_UART_TA006_CMD)
    BOX_LOG("UART TA006 CMD\n");
#endif
#if (SUPPORT_UART_TA012_CMD)
    BOX_LOG("UART TA012 CMD\n");
#endif
#endif

#if (SUPPORT_WQ_COMM)
    earbud_wq_comm_init();
    BOX_LOG("WQ CMD\n");
#endif
}

void app_user_deinit(void)
{
    
}


